<template>
    <div>
        <div id="container"></div>
        <a-drawer placement="right" :mask="false" :closable="false" :visible="true">
            <div>
                <h3>1.数据源</h3>
                <div>
                    <span>边界数据：</span>
                    <a-textarea v-model="dataSource.boundary" placeholder="[number,number][][]" :autoSize="{ maxRows: 3 }" />
                </div>
                <div>
                    <span>网格数据：</span>
                    <a-textarea v-model="dataSource.grid" :autoSize="{ maxRows: 3 }" />
                </div>
            </div>
            <div>
                <h3>2.筛选数据</h3>
                <a-table
                    :columns="table.columns"
                    rowKey="countryName"
                    :dataSource="table.data"
                    :pagination="false"
                    size="small"
                    :scroll="{ y: 200 }"
                    :rowSelection="{ selectedRowKeys: table.select, onChange: onSelectChange }"
                />
            </div>
            <div>
                <h3>3.工具</h3>
                <a-button class="btn" type="primary" @click="createPolygonEditor">新建工具</a-button>
                <a-button class="btn" type="primary" @click="openPolygonEditor">开始编辑</a-button>
                <a-button class="btn" type="primary" @click="closePolygonEditor">结束编辑</a-button>
            </div>
            <div>
                <h3>4.输出结果</h3>
                <a-textarea v-model="result" :autoSize="{ minRows: 3, maxRows: 5 }" />
            </div>
        </a-drawer>
        <a-modal v-model="showModal" :width="500" footer>
            <div style="textAlign:center">
                <span>村名：</span>
                <a-input v-model="modal.countryName" style="width:400px;marginBottom:10px" />
                <span>坐标：</span>
                <a-input v-model="modal.position" style="width:400px;marginBottom:10px" />
                <a-button type="primary" @click="setResult">{{ editIndex === null ? '新增' : '修改' }}</a-button>
            </div>
        </a-modal>
    </div>
</template>

<script lang="ts">
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/ban-ts-ignore */
import { Component, Vue, Watch } from 'vue-property-decorator';
import { loadAMap, createPolygon, createText } from '@/utils/map';
import { handleGridData, setCountryName } from '@/utils/transform';
// @ts-ignore
import coordtransform from 'coordtransform';

type IAny = { [T: string]: any };
type GridItem<T> = {
    id?: string;
    name?: string;
    parentId?: string;
    coorId?: string;
    parentName: string;
    data: T;
};
type GridFGItem = {
    parentName: string;
    position: [number, number];
    data: number[][];
};
type Path = [number, number][];
type DataSource = {
    boundary: string;
    grid: string;
};

@Component
export default class App extends Vue {
    dataSource: DataSource = {
        boundary: '',
        grid: ''
    };
    table = {
        columns: [{ title: '村名', dataIndex: 'countryName' }],
        data: [] as { countryName: string }[],
        select: [] as string[]
    };
    polyEditor!: IAny;
    showModal = false;
    result = '';
    modal = {
        countryName: '',
        position: ''
    };
    editIndex = null;

    @Watch('dataSource.boundary')
    setBoundarySource(newValue: string) {
        this.$emit('addBoundary', newValue);
    }
    @Watch('dataSource.grid')
    setGridSource(newValue: string) {
        this.$emit('addGridSource', newValue);
    }
    @Watch('table.select')
    setMapGrid(newValue: string[]) {
        this.$emit('filterGrid', newValue);
    }
    onSelectChange(select: any) {
        this.table.select = select;
    }
    @Watch('result')
    setGrid(newValue: string) {
        this.$emit('addGrid', newValue);
    }

    createPolygonEditor() {
        this.editIndex = null;
        this.polyEditor.close();
        this.polyEditor.setTarget();
        this.polyEditor.open();
    }
    openPolygonEditor() {
        this.polyEditor.open();
    }
    closePolygonEditor() {
        this.showModal = true;
        const { countryName, position } = this.polyEditor.getTarget().getExtData();
        this.modal.countryName = countryName || '';
        this.modal.position = position || '';
    }
    setResult() {
        const { countryName, position } = this.modal;
        if (countryName && position) {
            const path = this.polyEditor
                .getTarget()
                .getPath()
                .map((vo: { lng: string; lat: string }) => [vo.lng, vo.lat]);
            const item = { countryName, position, path };
            if (position.indexOf(',') === -1) {
                this.$message.error('坐标格式错误！');
                return;
            }
            if (!this.result) {
                this.result = JSON.stringify([item]);
            } else {
                const items = JSON.parse(this.result);
                this.editIndex === null ? items.push(item) : items.splice(this.editIndex, 1, item);
                this.result = JSON.stringify(items);
            }
            this.polyEditor.close();
            this.showModal = false;
        } else {
            this.$message.error('村名和坐标不能为空');
        }
    }

    validate(data: any, message: string, cb: Function) {
        let err, jsonData;
        try {
            jsonData = JSON.parse(data);
        } catch (e) {
            err = e;
        }
        if (Array.isArray(jsonData) && !err) {
            cb(jsonData);
        } else {
            this.$message.error(message);
        }
    }

    setDblclick(polygon: any) {
        polygon.on('dblclick', () => {
            // const result = JSON.parse(this.result);
            // const countryName = polygon.getExtData().countryName;
            // this.editIndex = result.findIndex((vo: any) => vo.countryName === countryName);
            this.polyEditor.setTarget(polygon);
            this.polyEditor.open();
        });
    }

    created() {
        loadAMap().then(AMap => {
            const map = new AMap.Map('container', {
                center: [113.746262, 23.046237],
                layers: [
                    //使用多个图层
                    new AMap.TileLayer.Satellite(),
                    new AMap.TileLayer.RoadNet()
                ]
            });
            this.polyEditor = new AMap.PolygonEditor(map);
            this.polyEditor.on('add', (data: IAny) => {
                const polygon = data.target;
                polygon.setOptions({ zIndex: 55 });
                this.polyEditor.addAdsorbPolygons(polygon);

                polygon.on('dblclick', (e: any) => {
                    const path = e.target.getPath().map((v: any) => v.toString().split(','));
                    console.log('path', JSON.stringify(path));
                    // const result = JSON.parse(this.result);
                    // const countryName = polygon.getExtData().countryName;
                    // this.editIndex = result.findIndex((vo: any) => vo.countryName === countryName);
                    this.polyEditor.setTarget(polygon);
                    this.polyEditor.open();
                });
                this.setDblclick(polygon);
            });
            this.polyEditor.on('end', (data: any) => {
                if (data.target) {
                    const polygon = data.target;
                    const { countryName, position } = this.modal;
                    polygon.setOptions({ extData: { type: 'polyEditor', countryName, position } });
                }
            });

            // 画边界
            this.$on('addBoundary', (path: any) => {
                this.validate(path, '边界数据格式错误！', (path: any) => {
                    const boundaryPolygon = map.getAllOverlays('polygon').filter((vo: any) => !vo.getExtData().countryName);
                    map.remove(boundaryPolygon);

                    const boundaryPath = path[0];
                    const boundary = createPolygon(AMap)(boundaryPath, { strokeColor: 'red', fillOpacity: 0, strokeWeight: 5 });
                    this.polyEditor.addAdsorbPolygons(boundary);
                    map.add(boundary);
                    map.setFitView(boundary);
                });
            });

            // 画网格(源数据)
            this.$on('addGridSource', (paths: any) => {
                this.validate(paths, '网格数据格式错误！', (paths: any) => {
                    const gridPaths = [...handleGridData(paths)];
                    this.table.data = gridPaths.map(vo => ({ countryName: setCountryName(vo.countryName) }));

                    this.$on('filterGrid', (filters: string[]) => {
                        const filterGridPaths = gridPaths.filter(vo => filters.indexOf(setCountryName(vo.countryName)) > -1);
                        const polygons = map.getAllOverlays('polygon');
                        const gridPolygons = polygons.filter((vo: any) => vo.getExtData().type === 'gridSource');
                        map.remove(gridPolygons);

                        filterGridPaths.map(vo => {
                            const fillColor = '#' + Math.floor(Math.random() * 16777215).toString(16);
                            const gridPath = vo.path.map(i => i.map(s => coordtransform.wgs84togcj02(s[0], s[1]) as number[]));
                            const polygon = gridPath.map(vo => createPolygon(AMap)(vo, { fillColor, extData: { type: 'gridSource' } }));
                            this.polyEditor.addAdsorbPolygons(polygon);
                            map.add(polygon);
                        });
                    });
                });
            });

            // 画网格(输出数据)
            this.$on('addGrid', (paths: any) => {
                this.validate(paths, '输出数据格式错误！', (paths: any) => {
                    const polygons = map.getAllOverlays('polygon');
                    const polyEditorPolygon = polygons.filter((vo: any) => vo.getExtData().type === 'polyEditor');
                    polyEditorPolygon.length > 0 && map.remove(polyEditorPolygon);

                    const texts = map.getAllOverlays('text');
                    map.remove(texts);

                    paths.map((vo: any) => {
                        const { countryName, position, path } = vo;
                        const fillColor = '#' + Math.floor(Math.random() * 16777215).toString(16);
                        const polygon = createPolygon(AMap)(path, { fillColor, zIndex: 60, extData: { type: 'polyEditor', countryName, position } });
                        this.setDblclick(polygon);
                        this.polyEditor.addAdsorbPolygons(polygon);

                        const text = createText(AMap)(vo.position.split(','), { text: vo.countryName });

                        text.on('dragend', (e: any) => {
                            const newPosition = e.target.getPosition().toString();
                            const item = paths.find((v: any) => v.countryName === countryName);
                            item.position = newPosition;
                            this.result = JSON.stringify(paths);
                        });

                        map.add([polygon, text]);
                    });
                });
            });
        });
    }
}
</script>

<style lang="scss">
#container {
    height: 100vh;
}
body {
    margin: 0;
}
.btn {
    margin: 0 5px 5px 0;
}
</style>
